package com.example.fill;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PointF;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

import androidx.annotation.Nullable;

import java.util.Arrays;
import java.util.List;

public class Control extends View {

    private PointF touchCenter = new PointF();
    private PointF moveLocal = new PointF();
    private Paint circlePaint = new Paint();
    private Paint fillPaint = new Paint();

    private final int circleRadius = 200;

    private Listener listener;

    public Control(Context context) {
        super(context);
        init();
    }

    public Control(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public Control(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }


    private void init() {
        circlePaint.setStyle(Paint.Style.STROKE);
        circlePaint.setColor(Color.BLACK);
        circlePaint.setStrokeWidth(2);
        circlePaint.setAntiAlias(true);

        fillPaint.setStyle(Paint.Style.FILL);
        fillPaint.setColor(Color.BLACK);
        fillPaint.setAntiAlias(true);
        fillPaint.setStrokeWidth(5);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int widMode = MeasureSpec.getMode(widthMeasureSpec);
        int heiMode = MeasureSpec.getMode(heightMeasureSpec);
        int size = 0;
        if (widMode == MeasureSpec.EXACTLY) {
            size = MeasureSpec.getSize(widthMeasureSpec);
        } else if (heiMode == MeasureSpec.EXACTLY) {
            size = MeasureSpec.getSize(heightMeasureSpec);
        } else {
            size = 320;
        }

        setMeasuredDimension(size, size);
        touchCenter.x = getMeasuredWidth() / 2;
        touchCenter.y = getMeasuredHeight() / 2;
        moveLocal.x = touchCenter.x;
        moveLocal.y = touchCenter.y;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        canvas.drawCircle(touchCenter.x, touchCenter.y, circleRadius, circlePaint);
        canvas.drawCircle(moveLocal.x, moveLocal.y, 60, fillPaint);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                touchCenter.x = event.getX();
                touchCenter.y = event.getY();
                moveLocal.x = touchCenter.x;
                moveLocal.y = touchCenter.y;
                if (listener != null) {
                    listener.onMove(new MoveWrapper(0, MoveState.STAND));
                }
                break;
            case MotionEvent.ACTION_MOVE:
                float moveX = event.getX();
                float moveY = event.getY();

                float pointInCircle = isPointInCircle(moveX, moveY, touchCenter.x, touchCenter.y);
                if (pointInCircle <= circleRadius) {
                    moveLocal.x = moveX;
                    moveLocal.y = moveY;
                } else {
                    PointF nearestPointOnOuterCircle = getNearestPointOnOuterCircle(moveX, moveY);
                    moveLocal.x = nearestPointOnOuterCircle.x;
                    moveLocal.y = nearestPointOnOuterCircle.y;
                }
                if (listener != null) {
                    float x = moveX - touchCenter.x;
                    if (x > 0) {
                        listener.onMove(new MoveWrapper(0, MoveState.RIGHT));
                    } else {
                        listener.onMove(new MoveWrapper(0, MoveState.LEFT));
                    }
                }
                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                moveLocal.x = touchCenter.x;
                moveLocal.y = touchCenter.y;
                if (listener != null){
                    listener.onMove(new MoveWrapper(0,MoveState.STAND));
                }
                break;
        }
        invalidate();
        return true;
    }

    private PointF getNearestPointOnOuterCircle(float x, float y) {
        float angle = (float) Math.atan2(y - getHeight() / 2f, x - getWidth() / 2f);
        float nearestX = touchCenter.x + circleRadius * (float) Math.cos(angle);
        float nearestY = touchCenter.y + circleRadius * (float) Math.sin(angle);
        return new PointF(nearestX, nearestY);
    }


    private float isPointInCircle(float x, float y, float centerX, float centerY) {
        return (float) Math.sqrt(Math.pow(x - centerX, 2) + Math.pow(y - centerY, 2));
    }

    public void setListener(Listener listener) {
        this.listener = listener;
    }

    public interface Listener {

        void onMove(MoveWrapper wrapper);

    }

}
